﻿<!DOCTYPE HTML>
<html lang="zh">
<head>
<title>在报错时 - 语法 &amp; 使用 | AutoHotkey v2</title>
<meta name="description" content="The 在报错时 function specifies a function to 运行 automatically when an unhandled error occurs." />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link href="../static/theme.css" rel="stylesheet" type="text/css" />
<script src="../static/content.js" type="text/javascript"></script>
<script type="text/javascript">$(function(){0<=window.navigator.userAgent.toLowerCase().indexOf("ucbrowser")&&CaoNiMaDeUc()})</script>
</head>
<body>

<h1>在报错时</h1>
<p>指定在未处理错误发生时自动运行的<a href="../Functions.htm">函数</a>.</p>

<pre class="Syntax"><span class="func">在报错时</span> 检索函数 <span class="optional">, AddRemove</span></pre>

<h2 id="Parameters">参数</h2>
<dl>

  <dt>检索函数</dt>
  <dd>
    <p>类型: <a href="../Concepts.htm#strings">字符串</a>或<a href="../Concepts.htm#objects">对象</a></p>
    <p>当未处理的错误发生时调用的函数的名称或<a href="../objects/Functor.htm">函数对象</a>. 请参阅下面的 <em>Callback</em>.</p>
  </dd>
  
  <dt>AddRemove</dt>
  <dd>
    <p>类型: <a href="../Concepts.htm#numbers">整数</a></p>
    <p>下列值之一:<br>
  <strong>1</strong>(默认): 在所有之前注册的函数之后调用该函数.<br>
  <strong>-1</strong>: 在所有之前注册的函数之前调用该函数.<br>
  <strong>0</strong>: 不调用该函数.</p>
  </dd>

</dl>

<h2>Callback</h2>
<p>回调函数应该接受两个参数:</p>
<pre class="Syntax"><i>Callback</i>(Thrown, Mode)</pre>
<dl>
  <dt>Thrown</dt>
  <dd><em>Thrown</em> 是抛出的值, 通常是一个<a href="Throw.htm#Exception">异常对象</a>.</dd>
  <dt>Mode</dt>
  <dd>以下字符串之一:
    <ul>
      <li><code>"Return"</code>: <em>Thrown</em> 的是一个可持续的运行时错误. 如果回调返回 -1, 则线程继续; 否则线程退出.</li>
      <li><code>"Exit"</code>: <em>Thrown</em> 是一个不可持续的运行时错误或脚本 <a href="Throw.htm">thrown</a> 的一个值. 线程将退出.</li>
      <li><code>"ExitApp"</code>: <em>Thrown</em> 是一个关键的运行时错误, 如 动态库调用 检测到的损坏. 程序将退出.</li>
    </ul>
  </dd>
</dl>
<p>回调函数可以返回以下值之一(其他值是为将来使用而保留的, 应该避免):</p>
<ul>
  <li><code>0</code>, <code>""</code> 或没有 <code>返回</code>: 允许错误处理正常进行.</li>
  <li><code>1</code>: 抑制默认错误对话框和任何剩余的错误回调.</li>
  <li><code>-1</code>: 同上, 但如果 <em>Mode</em> 为 <code>"Return"</code>, 则允许继续执行当前线程.</li>
</ul>

<h2 id="Remarks">备注</h2>
<p><em>检索函数</em> 只会被调用来处理通常会导致显示错误消息的错误或异常. 加载时的错误无法调用, 因为在加载脚本完毕之前无法调用 在报错时.</p>
<p><em>检索函数</em> 在当前<a href="../misc/Threads.htm">线程</a>中被调用, 在线程退出之前(即在调用堆栈展开之前).</p>

<h2 id="Related">相关</h2>
<p><a href="Try.htm">Try</a>, <a href="Catch.htm">捕获</a>, <a href="Throw.htm">报错</a>, <a href="OnExit.htm">在退出时</a></p>

<h2 id="Examples">示例</h2>
<div class="ex" id="ExBasic">
<p><a href="#ExBasic">#1</a>: 将错误记录到文本文件, 而不是显示给用户.</p>
<pre>
在报错时 "LogError"
i := 整数("cause_error")

LogError(异常, mode) {
    附加 "Error on line " 异常.Line ": " 异常.Message "`n"
        , "errorlog.txt"
    返回 true
}
</pre>
</div>

<div class="ex" id="ExAccumulator">
<p><a href="#ExAccumulator">#2</a>: 使用 在报错时 来实现其他错误处理方法. 注意: 当 <a href="Try.htm">Try</a> 处于活动状态时, 在报错时 是无效的.</p>
<pre>
AccumulateErrors()
{
    local ea := ErrorAccumulator.new()
    ea.Start()
    返回 ea
}

class ErrorAccumulator
{
    Errors := []                        <em>; 累计错误数组.</em>
    _cb := 检索函数("AccumulateError").Bind(this.Errors)
    Start() => 在报错时(this._cb, -1)    <em>; 先注册 cb.</em>
    Stop() => 在报错时(this._cb, 0)      <em>; 取消注册 cb.</em>
    Last => this.Errors[-1]             <em>; 最近的错误.</em>
    Count => this.Errors.Length         <em>; 累计错误的数目.</em>
    __item[i] => this.Errors[i]         <em>; 索引.</em>
    __delete() => this.Stop()           <em>; 用于与函数范围绑定.</em>
}

<em>; 这是 在报错时 回调函数. 'errors' 是通过 Bind() 给定的值.</em>
AccumulateError(errors, e, mode)
{
    如果 mode != "Return" <em>; 不可继续.</em>
        返回
    如果 e.What = "" <em>; 表达式缺陷或类似的, 不是内置函数.</em>
        返回
    try {
        <em>; 尝试将错误打印到 stdout.</em>
        附加 格式化字符串("{1} ({2}) : ({3}) {4}`n", e.File, e.Line, e.What, e.Message), "*"
        如果 包含属性(e, "extra")
            附加 "     Specifically: " e.Extra "`n", "*"
    }
    errors.Push(e)
    返回 -1 <em>; 继续.</em>
}

RearrangeWindows()
{
    <em>; 开始在 'err' 中累积错误.</em>
    local err := AccumulateErrors()

    <em>; 做一些可能失败的事情...</em>
    获取显示器工作区域 , left, top, right, bottom
    width := (right-left)//2, height := bottom-top
    移动窗口 left, top, width, height, 内_脚本全路径
    移动窗口 left+width, top, width, height, "AutoHotkey v2 Help"

    <em>; 检查是否发生任何错误.</em>
    如果 err.Count
        信息框 err.Count " error(s); last error at line #" err.Last.Line
    否则
        信息框 "No errors"

    <em>; 当变量超出作用域时, Stop 会被自动调用,
    ; 因为只有我们有一个对象的引用. 这将导致 在报错时
    ; 被调用来解除回调.
    ; err.Stop()</em>
}

<em>; 调用抑制和累积错误的测试函数.</em>
RearrangeWindows()
<em>; 调用另一个函数来显示恢复正常的错误行为.</em>
移动窗口 0, 0, 0, 0, "non-existent window"
</pre>
</div>

</body>
</html>